}
pub fn rustc(&self) -> CargoResult<&Rustc> {
- self.rustc.get_or_try_init(|| Rustc::new(self.get_tool("rustc")?))
+ self.rustc.get_or_try_init(|| Rustc::new(self.get_tool("rustc")?,
+ self.maybe_get_tool("rustc_wrapper")?))
}
pub fn cargo_exe(&self) -> CargoResult<&Path> {
}
}
- fn get_tool(&self, tool: &str) -> CargoResult<PathBuf> {
+ /// Look for a path for `tool` in an environment variable or config path, but return `None`
+ /// if it's not present.
+ fn maybe_get_tool(&self, tool: &str) -> CargoResult<Option<PathBuf>> {
let var = tool.chars().flat_map(|c| c.to_uppercase()).collect::<String>();
if let Some(tool_path) = env::var_os(&var) {
- return Ok(PathBuf::from(tool_path));
+ return Ok(Some(PathBuf::from(tool_path)));
}
let var = format!("build.{}", tool);
if let Some(tool_path) = self.get_path(&var)? {
- return Ok(tool_path.val);
+ return Ok(Some(tool_path.val));
}
- Ok(PathBuf::from(tool))
+ Ok(None)
+ }
+
+ /// Look for a path for `tool` in an environment variable or config path, defaulting to `tool`
+ /// as a path.
+ fn get_tool(&self, tool: &str) -> CargoResult<PathBuf> {
+ self.maybe_get_tool(tool)
+ .map(|t| t.unwrap_or(PathBuf::from(tool)))
}
}
pub struct Rustc {
pub path: PathBuf,
+ pub wrapper: Option<PathBuf>,
pub verbose_version: String,
pub host: String,
}
///
/// If successful this function returns a description of the compiler along
/// with a list of its capabilities.
- pub fn new(path: PathBuf) -> CargoResult<Rustc> {
+ pub fn new(path: PathBuf, wrapper: Option<PathBuf>) -> CargoResult<Rustc> {
let mut cmd = util::process(&path);
cmd.arg("-vV");
-
+
let output = cmd.exec_with_output()?;
-
+
let verbose_version = String::from_utf8(output.stdout).map_err(|_| {
internal("rustc -v didn't return utf8 output")
})?;
Ok(Rustc {
path: path,
+ wrapper: wrapper,
verbose_version: verbose_version,
host: host,
})
}
pub fn process(&self) -> ProcessBuilder {
- util::process(&self.path)
+ if let Some(ref wrapper) = self.wrapper {
+ let mut cmd = util::process(wrapper);
+ {
+ cmd.arg(&self.path);
+ }
+ cmd
+ } else {
+ util::process(&self.path)
+ }
}
}
relative to the current working directory.
* `RUSTC` - Instead of running `rustc`, Cargo will execute this specified
compiler instead.
+* `RUSTC_WRAPPER` - Instead of simply running `rustc`, Cargo will execute this
+ specified wrapper instead, passing as its commandline arguments the rustc
+ invocation, with the first argument being rustc.
* `RUSTDOC` - Instead of running `rustdoc`, Cargo will execute this specified
`rustdoc` instance instead.
* `RUSTFLAGS` - A space-separated list of custom flags to pass to all compiler
assert_that(p.cargo_process("run").arg("--bin").arg("foo"),
execs().with_status(0));
}
+
+#[test]
+fn rustc_wrapper() {
+ // We don't have /usr/bin/env on Windows.
+ if cfg!(windows) { return }
+
+ let p = project("foo")
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]));
+
+ assert_that(p.cargo_process("build").arg("-v").env("RUSTC_WRAPPER", "/usr/bin/env"),
+ execs().with_stderr_contains(
+ "[RUNNING] `/usr/bin/env rustc --crate-name foo [..]")
+ .with_status(0));
+}
pub mod support;
pub mod install;
-thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());
+thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc"), None).unwrap());
pub fn rustc_host() -> String {
RUSTC.with(|r| r.host.clone())
.env_remove("__CARGO_DEFAULT_LIB_METADATA")
.env_remove("RUSTC")
.env_remove("RUSTDOC")
+ .env_remove("RUSTC_WRAPPER")
.env_remove("RUSTFLAGS")
.env_remove("CARGO_INCREMENTAL")
.env_remove("XDG_CONFIG_HOME") // see #2345